package HGin

import (
	"github.com/gin-gonic/gin"
	"reflect"
	"strings"
)

func Register(engine *gin.Engine, objs ...interface{}) {
	NewRouteGroup(engine).Bind(objs...)
}

var (
	mMap = map[string]struct{}{
		"POST":    struct{}{},
		"GET":     struct{}{},
		"PUT":     struct{}{},
		"PATCH":   struct{}{},
		"DELETE":  struct{}{},
		"OPTIONS": struct{}{},
		"HEAD":    struct{}{},
		"Any":     struct{}{},
	}
	defaultMethod = "POST"
)

func getActionMethod(methodName string, methods map[string]interface{}) []string {
	m, ok := methods[methodName]
	if ok {
		switch m.(type) {
		case string:
			return []string{getUpperMethod(m.(string))}
		case []string:
			mlist := m.([]string)
			m01 := make([]string, 0, len(mlist))
			m02 := make(map[string]struct{}, len(mlist)) // 防止重复添加路由
			for _, v := range mlist {
				v1 := getUpperMethod(v)
				if strings.ToUpper(v) != v1 {
					continue
				}
				if _, ok := m02[v1]; ok {
					continue
				}
				m02[v1] = struct{}{}
				m01 = append(m01, v1)
			}
			return m01
		}
	}
	return []string{"POST"}
}

func getUpperMethod(method string) string {
	if _, ok := mMap[strings.ToUpper(method)]; ok {
		return strings.ToUpper(method)
	}
	return defaultMethod
}

// 解析结构体
func parseStruct(v reflect.Value) (prefix string, handlerFn []gin.HandlerFunc, method map[string]interface{}) {
	return getPrefix(v),
		getMiddleWare(v.FieldByName("Middleware")),
		getMethod(v)
}

// 获取前缀
func getPrefix(v reflect.Value) string {
	pre := v.FieldByName("Prefix")
	if pre.Kind() != reflect.String {
		return ""
	}
	return get_prefix(pre.String())
}

func get_prefix(str string) string {
	if str == "" {
		return ""
	}
	return "/" + strings.Trim(str, "/")
}

// 获取中间件
func getMiddleWare(middleware reflect.Value) []gin.HandlerFunc {
	handlerFn := make([]gin.HandlerFunc, 0, 5)
	if middleware.Kind() == reflect.Slice {
		hFunc := middleware.Interface().([]gin.HandlerFunc)
		handlerFn = append(handlerFn, hFunc...)
	}
	return handlerFn
}

// 获取方法列表
func getMethod(v reflect.Value) (m map[string]interface{}) {
	method := v.FieldByName("Method")
	if method.Kind() == reflect.Map && method.Len() > 0 {
		return method.Interface().(map[string]interface{})
	}
	return
}

// gin默认的调用函数
// method: 反射对象上的方法
func defaultFun(method reflect.Value) func(ctx *gin.Context) {
	return func(ctx *gin.Context) {
		method.Call([]reflect.Value{reflect.ValueOf(ctx)})
	}
}

func convertPath(prefix, p string) string {

	prefix = prefix + "/"

	if prefix != "/" {
		prefix = "/" + strings.Trim(prefix, "/")
	}

	if p == "" {
		return prefix
	}

	if strings.Contains(p, ".") {
		strs := strings.Split(p, ".")
		for i, str := range strs {
			strs[i] = HumpToSnake(str)
		}
		return prefix + "/" + strings.Join(strs, "/")
	}

	return prefix + "/" + p
}

// HumpToSnake
// 驼峰名称转蛇形
func HumpToSnake(s string) string {
	data := make([]byte, 0, len(s)*2)
	j := false
	num := len(s)
	for i := 0; i < num; i++ {
		d := s[i]
		// or通过ASCII码进行大小写的转化
		// 65-90（A-Z），97-122（a-z）
		//判断如果字母为大写的A-Z就在前面拼接一个_
		if i > 0 && d >= 'A' && d <= 'Z' && j {
			data = append(data, '_')
		}
		if d != '_' {
			j = true
		}
		data = append(data, d)
	}
	//ToLower把大写字母统一转小写
	return strings.ToLower(string(data[:]))
}
